home *** CD-ROM | disk | FTP | other *** search
/ Network Supervisor's Toolkit / Network Supervisor's Toolkit.iso / tools / nwtp06 / phone.pas < prev    next >
Pascal/Delphi Source File  |  1996-07-10  |  25KB  |  819 lines

  1. Program Phone;
  2. {$IFDEF VER70}
  3. {$A+,B-,D-,E-,F-,G-,I-,L-,N-,O-,P+,Q-,R-,S-,T-,V-,X+}
  4. {$ELSE}
  5. {$A+,B-,D-,E-,F-,G-,I-,L-,N-,O-,R-,S-,V-,X+}
  6. {$ENDIF}
  7.  
  8. { Source code for Borland/Turbo Pascal 6/7.
  9.   To be compiled with NwTP version 0.6 or higher.
  10.   NwTP is a FreeWare Netware Interface for Pascal.
  11. }
  12.  
  13. { Based on the phone.pas program by Eduardo M. Serrat,
  14.   as published in Dr.Dobbs #207, November 1993.
  15.  
  16.   The NwTP units and this adaption of his program are
  17.   (c) 1993,1995 by Rene Spronk ,Groningen, the Netherlands. }
  18.  
  19. uses dos,crt,nwMisc,nwBindry,nwConn,nwMess,nwServ,nwIPX;
  20.  
  21. const Socket  = $80C3;
  22.       { This socket was assigned by Novell to an IPX Chatprogram by OXXI }
  23.       { Don't use this program in conjunction with theirs..              }
  24. Var
  25.    SendECB,
  26.    ListenECB      :TEcb;                     { Definition of ECBs        }
  27.    SendIpxHeader,
  28.    ListenIPXheader:TIpxHeader;               { Definition of IPX Headers }
  29.    SendData,
  30.    ReadData       :Array [1..100] of Byte;    { Data area of packets      }
  31.    readflg        :Boolean;  { Flag to signal received packets }
  32.  
  33.    MyConnNbr      :Byte;
  34.    MyAddress      :TinternetworkAddress;
  35.    MyName         :String;
  36.    MyServerId     :Byte;
  37.    MyServerName   :String;
  38.    myx,myy        :Byte;  { my viewport cursor position }
  39.  
  40.    RconnNbr       :Byte;
  41.    Raddress       :TinterNetworkAddress;
  42.    Rname          :String;
  43.    RfullName      :String;
  44.    RserverID      :Byte;
  45.    RserverName    :String;
  46.    LocalTarget    :TnodeAddress;  { Node Address of bridge to remote address }
  47.  
  48.    NewStack       :Array[1..256] of Word;   { !! used by ESR }
  49.    StackBottom    :Word;                    { !! used by ESR }
  50.    HeapCheckPtr   :pointer;  { Pointer that holds heapPointers }
  51.  
  52. {---------------------------------------------------------------------------}
  53.  
  54. Procedure CheckError(b:Boolean;errCode:Word; mess:String);
  55. begin
  56. IF b
  57.  then begin
  58.       writeln;
  59.       CASE errCode of
  60.        { main body: 0000-000F }
  61.        $0001:writeln('IPX not installed.');
  62.        $0002:writeln('Error opening socket.');
  63.        { Procedure whoami }
  64.        $0010:writeln('Error whilst determining connectionnumber.');
  65.        $0011:writeln('Error determining internet address.');
  66.        $0012:writeln('Error retreiving connection information.');
  67.        { Procedure process input command }
  68.        $0022:writeln('Servername ',mess,' is invalid.');
  69.        $0023:writeln('Error interpreting connection number parameter :',mess);
  70.        $0025:begin
  71.              writeln('The supplied username is not unique,');
  72.              writeln('or the target user isn''t logged in.');
  73.              end;
  74.        $0026:writeln('Please select a target user from the above list.');
  75.        $0027:writeln('Phone cancelled.');
  76.        { handshake with sender }
  77.        $0032:writeln('Packet received from a user claiming to be ConnectionNumber $',mess);
  78.        { Sendbroadcast message in Procedure HandshakeWithreceiver }
  79.        $1000: writeln('Error: Broadcasting a message to the target user failed.');
  80.        $10FC: begin
  81.               Writeln('The target user is logged in, but appears not to be at his/her workstation:');
  82.               writeln('The (last) message was rejected, message buffer for the target station is full.');
  83.               end;
  84.        $10FD: begin
  85.               Writeln('The connection number of the target user has become invalid,');
  86.               Writeln('Most likely because the user has logged out.');
  87.               end;
  88.        $10FF: begin
  89.               Writeln('The target user is logged in, but has blocked incoming messages.');
  90.               end;
  91.       else writeln('An unspecified error occurred.');
  92.       end; {case }
  93.       if errCode>$000F then IPXcloseSocket(socket);
  94.       if errCode>$001F
  95.        then begin
  96.             SetPreferredConnectionId(MyServerId);
  97.             release(HeapCheckPtr);
  98.             end;
  99.       if ((errCode=$0026) or (errCode=$0027))
  100.        then halt(0)
  101.        else halt(1);
  102.       end;
  103. end;
  104.  
  105. {-----------------------------------------------------------------------------}
  106.  
  107. Function Confirm:Boolean;
  108. Var ch:char;
  109. begin
  110. repeat
  111.   repeat {} until keypressed;
  112.   ch:=readkey;
  113.   if ch=#0 then ch:=readkey;
  114. until ch IN ['y','Y','n','N'];
  115. Confirm:=((ch='Y') or (ch='y'))
  116. end;
  117.  
  118. {-----------------------------------------------------------------------------}
  119.  
  120. {$F+}
  121. Procedure ESRproc;
  122. begin
  123.  ReadFlg:=true;
  124. end;
  125.  
  126. Procedure ESRHandler; assembler;
  127. asm { ES:SI are the only valid registers when entering this Procedure ! }
  128.     mov dx, seg stackbottom
  129.     mov ds, dx
  130.  
  131.     mov dx,ss  { setup of a new local stack }
  132.     mov bx,sp  { ss:sp copied to dx:bx}
  133.     mov ax,ds
  134.     mov ss,ax
  135.     mov sp,offset stackbottom
  136.     push dx
  137.     push bx
  138.  
  139.     CALL EsrProc
  140.  
  141.     pop bx
  142.     pop dx
  143.     mov sp,bx
  144.     mov ss,dx
  145. end;
  146. {$F-}
  147.  
  148. {-----------------------------------------------------------------------------}
  149.  
  150. Function SameAddress(Var a,b):Boolean;
  151. { check if networkaddress a and b have the same net and node address }
  152. Type Taddress=Array[1..10] of char;
  153. Var addrA:Taddress ABSOLUTE a;
  154.     addrB:Taddress ABSOLUTE b;
  155. begin
  156. SameAddress:=(addrA=addrB);
  157. end;
  158.  
  159. {----------------------------------------------------------------------------}
  160.  
  161. Function Time:String;
  162.    Function LeadingZero(w:Word):String;
  163.    Var s : String;
  164.    begin
  165.    Str(w:0,s);
  166.    if Length(s) = 1
  167.     then s := '0' + s;
  168.    LeadingZero := s;
  169.    end;
  170. Var h, m, s, hund : Word;
  171. begin
  172. GetTime(h,m,s,hund);
  173. Time:=LeadingZero(h)+':'+LeadingZero(m)+':'+LeadingZero(s);
  174. end;
  175.  
  176. {-----------------------------------------------------------------------------}
  177. Procedure HandshakeWithReceiver;
  178. const Progress  :  Array [1..4] of char = ('/','─','\','|');
  179. Var
  180.    SecondInd   :Word;
  181.    ProgressInd :Byte;
  182.    x,y         :Byte;
  183.    KeyNbr      :Byte;
  184.    ConnUp      :Boolean;
  185.  
  186.    ObjName     :String;
  187.    ObjType     :Word;
  188.    ObjId       :LongInt;
  189.    LogonTime   :TnovTime;
  190.  
  191.    Message     :String;
  192.    ConnList,
  193.    ResultList  :TconnectionList;
  194. begin
  195. Writeln('Calling User ',Rname);
  196. Write('Press <ESC> to cancel [ ]');
  197. x:=wherex-2; y:=wherey;
  198. Message:='User '+MyName+' is phoning you........... ['+Time+']';
  199. SecondInd:=0; ProgressInd:=1;
  200.  
  201. SetPreferredConnectionId(RserverId);
  202. ConnList[1]:=RconnNbr;
  203. SendBroadcastMessage(message,1,ConnList,ResultList);
  204. Checkerror(nwMess.result>0,$1000,'');
  205. CheckError(ResultList[1]>0,$1000+ResultList[1],'');
  206.  
  207. IPXListenForPacket(ListenECB);
  208.  
  209. KeyNbr:=$ff;
  210. ConnUp:=False;
  211. FillChar(SendData,SizeOf(SendData),#0);
  212. SendData[1]:=Hi(MyConnNbr);
  213. SendData[2]:=Lo(MyConnNbr);
  214. Move(MyServerName[1],SendData[3],ord(MyserverName[0]));
  215. Move(MyName[1],SendData[50],ord(Myname[0]));
  216.  
  217. repeat { send a packet every 4 seconds and a broadcast message every 30 seconds }
  218.   gotoxy(x,y);
  219.   write(Progress[ProgressInd]);
  220.   inc(ProgressInd);
  221.   if ProgressInd > 4
  222.    then begin
  223.         ProgressInd:=1;
  224.         IPXSendPacket(SendECB);
  225.         end;
  226.   inc(SecondInd);
  227.   if SecondInd = 30
  228.    then begin
  229.         SendBroadcastMessage(message,1,ConnList,ResultList);
  230.         Checkerror(nwMess.result>0,$1000,'');
  231.         CheckError(ResultList[1]>0,$1000+ResultList[1],'');
  232.         SecondInd:=0;
  233.         end;
  234.   delay(1000);
  235.   if readflg
  236.    then begin
  237.         writeln('recieved a packet..');
  238.          if not SameAddress(ListenIPXheader.source,Raddress)
  239.           then begin
  240.                readflg:=false;
  241.                IPXListenForPacket(ListenECB);
  242.                end
  243.           else ConnUp:=TRUE;
  244.         end;
  245.   if keypressed
  246.    then KeyNbr:=ord(readkey);
  247.  
  248. until (KeyNbr = $1b) or ConnUp;
  249.  
  250. if KeyNbr = $1b
  251.  then begin
  252.       Writeln;
  253.       Write('Wait...');
  254.       Delay(5000);
  255.       SendData[1]:=$1b;
  256.       IPXSendPacket(SendECB);
  257.       message:='The user phoning you canceled the call... ['+Time+']';
  258.       SendBroadcastMessage(message,1,ConnList,ResultList);
  259.       IpxCloseSocket(Socket);
  260.       SetPreferredConnectionID(MyServerId);
  261.       halt(1);
  262.       end;
  263. Writeln;
  264. Write('User ',Rname,' answered your call......!');
  265. delay(1200);
  266. ReadFlg:=false;
  267. end;
  268.  
  269. {--------------------------------------------------------------------------}
  270.  
  271. Procedure HandshakeWithSender;
  272. const Progress:Array [1..4] of char = ('/','─','\','|');
  273. Var p        :Byte;
  274.     ObjType  :Word;
  275.     ObjId    :LongInt;
  276.     LoginTime:TnovTime;
  277.     ticks    :Word;
  278.     x,y      :Word;
  279. begin
  280. Writeln('Listening for calls..');
  281. Write('Press <ESC> to cancel [ ]');
  282. x:=wherex-2; y:=wherey;
  283. IPXListenForPacket(ListenECB);
  284. p:=1;
  285. while(p<=4) and (not ReadFlg)
  286.  do begin
  287.     gotoxy(x,y);
  288.     write(Progress[p]);
  289.     delay(1200);
  290.     inc(p);
  291.     end;
  292. If not readflg
  293.  then begin
  294.       Writeln;
  295.       Writeln('Nobody is Calling you..........');
  296.       writeln;
  297.       writeln('( PHONE ? for help )');
  298.       IpxCloseSocket(Socket);
  299.       SetPreferredConnectionId(MyServerId);
  300.       halt(1);
  301.       end
  302. else  begin
  303.       readflg:=false;
  304.       Raddress:=ListenIPXheader.source;
  305.       Raddress.socket:=Socket;
  306.       RconnNbr:=(ReadData[1]*256)+ReadData[2];
  307.       ZstrCopy(RserverName,ReadData[3],47);
  308.       ZstrCopy(Rname,ReadData[50],47);
  309.       IPXGetLocalTarget(Raddress,LocalTarget,ticks);
  310.       IPXSetupSendECB(NIL, Socket, Raddress,
  311.                       Addr(SendData), SizeOf(SendData),
  312.                       SendIPXheader,SendECB);
  313.       IPXSendPacket(SendECB); { acknowledge by sending a packet. Packet contents unimportant. }
  314.       end;
  315. end;
  316.  
  317.  
  318. {-----------------------------------------------------------------------------}
  319.  
  320. Procedure InitWindows;
  321. Var i: Byte;
  322. begin
  323. ClrScr;
  324. myx:=1; myy:=1;
  325. gotoxy(1,1);
  326. write('╔'); for i:=2 to 79 do write('═'); write('╗');
  327. write('║'); for i:=2 to 79 do write(' '); write('║');
  328.  
  329. gotoxy(3,2);
  330. Write('User: '+MyName+' ░ Server: '+MyServerName);
  331. write(' ░ Connection: '); write(MyConnNbr);
  332. gotoxy(1,3);
  333. write('╚'); for i:=2 to 79 do write('═'); write('╝');
  334.  
  335. gotoxy(1,13);
  336. write('╔'); for i:=2 to 79 do write('═'); write('╗');
  337. write('║'); for i:=2 to 79 do write(' '); write('║');
  338.  
  339. gotoxy(3,14);
  340. Write('User: '+Rname+' ░ Server: '+RserverName);
  341. Write(' ░ Connection: '); write(RconnNbr);
  342. Gotoxy(1,15);
  343. write('╚'); for i:=2 to 79 do write('═'); write('╝');
  344.  
  345. gotoxy(26,25);
  346. Write('▒▒▒▓▓▓ Phone Utility ▓▓▓▒▒▒');
  347. gotoxy(1,1);
  348. HighVideo;
  349. end;
  350.  
  351. {-----------------------------------------------------------------------------}
  352.  
  353. Procedure Talk;
  354.  
  355.     Function Timeout(w1,w2:Word;sec:Byte):Boolean;
  356.     Var lw2:Longint;
  357.     begin
  358.     if w2<w1
  359.      then lw2:=$10000+w2
  360.      else lw2:=w2;
  361.     Timeout:=((lw2-w1) DIV 18)>sec;
  362.     end;
  363.  
  364.     Procedure MyWindow;
  365.     begin
  366.     Window(1,5,80,12);
  367.     gotoxy(myx,myy);
  368.     end;
  369.  
  370.     Procedure RemoteWindow;
  371.     begin
  372.     Window(1,17,80,24);
  373.     end;
  374.  
  375.  
  376. Var currMarker,
  377.     SendMarker,
  378.     ListenMarker:Word;
  379.     ch          :Char;
  380.     RlastChar,
  381.     RlastX,
  382.     RlastY      :byte;
  383. begin
  384. MyWindow;
  385. IPXListenForPacket(ListenECB);
  386. IPXSetupSendECB(NIL, Socket, Raddress, Addr(SendData), 7,
  387.           SendIPXheader,SendECB);  { make size of sendBuffer smaller }
  388. IPXgetIntervalMarker(SendMarker);
  389. ListenMarker:=SendMarker;
  390. SendData[1]:=$FF;
  391. RlastChar:=$FF;
  392.  
  393. REPEAT
  394.  if keypressed
  395.   then begin
  396.        MyWindow;
  397.        SendData[4]:=SendData[1];  { append last typed char to packet. }
  398.        SendData[5]:=SendData[2];  { original packet may have been lost }
  399.        SendData[6]:=SendData[3];  { Remember: IPX is unreliable ! }
  400.        ch:=readkey;
  401.        if ch=#0
  402.         then begin
  403.              ch:=readkey;
  404.              CASE ord(ch) of
  405.               75:begin { <- 'cursor left' }
  406.                  SendData[2]:=myx-1;
  407.                  if (myx=1) then SendData[2]:=1;
  408.                  gotoxy(SendData[2],myy);
  409.                  SendData[3]:=myy;
  410.                  SendData[1]:=$00;
  411.                  end;
  412.               77:begin { -> 'cursor right' }
  413.                  SendData[2]:=myx+1;
  414.                  if (myx=80) then SendData[2]:=80;
  415.                  gotoxy(SendData[2],myy);
  416.                  SendData[3]:=myy;
  417.                  SendData[1]:=$00;
  418.                  end;
  419.              else SendData[1]:=$FF;
  420.              end; {case}
  421.  
  422.              end
  423.         else begin
  424.              SendData[1]:=ord(ch);
  425.              SendData[2]:=myx;
  426.              SendData[3]:=myy;
  427.              Case ord(SendData[1]) of
  428.               8 :write(#8+#$20+#8); { backspace }
  429.               13:writeln;           { return    }
  430.              else write(chr(SendData[1]));
  431.              end; {case}
  432.              end;
  433.        myx:=wherex;
  434.        myy:=wherey;
  435.        IPXSendPacket(SendECB);           { send current and previous char }
  436.        IPXGetIntervalMarker(SendMarker);
  437.        end;
  438.  
  439.  if readflg
  440.   then begin
  441.        If SameAddress(ListenIPXheader.source,Raddress)
  442.         then begin
  443.              if (readData[4]<>$FF)
  444.               and (   (readData[4]<>RlastChar)
  445.                    or (readData[5]<>Rlastx)
  446.                    or (readData[6]<>Rlasty)
  447.                   )
  448.              then begin   { if we missed a packet, display char now }
  449.                   RemoteWindow;
  450.                   Gotoxy(ReadData[5],ReadData[6]);
  451.                   CASE ReadData[4] of
  452.                    0:begin { don't print, cursor movement only }
  453.                      end;
  454.                    8:write(#8+#$20+#8);  { backspace }
  455.                   13:writeln;            { return    }
  456.                   else write(chr(ReadData[1]));
  457.                   end;{case}
  458.                   end;
  459.  
  460.              if ReadData[1]<>$FF
  461.               then begin
  462.                    RemoteWindow;
  463.                    Gotoxy(ReadData[2],ReadData[3]);
  464.                    CASE ReadData[1] of
  465.                     0:begin { don't print, cursor movement only }
  466.                       end;
  467.                     8:write(#8+#$20+#8);
  468.                    13:writeln;
  469.                    else write(chr(ReadData[1]));
  470.                    end;{case}
  471.                    end;
  472.              RlastChar:=ReadData[1];
  473.              RlastX   :=ReadData[2];
  474.              RlastY   :=ReadData[3];
  475.              IPXGetIntervalMarker(ListenMarker);
  476.              end;
  477.        readflg:=false;
  478.        IPXListenForPacket(ListenECB);
  479.        end;
  480.  
  481.  IPXRelinquishControl;
  482.  IPXGetIntervalMarker(currMarker);
  483.  IF Timeout(SendMarker,currMarker,5)  { send an "I'm alive" msg after 5 idle secs }
  484.   then begin
  485.        SendData[4]:=SendData[1];  { redundant info: append last char to packet. }
  486.        SendData[5]:=SendData[2];
  487.        SendData[6]:=SendData[3];
  488.        SendData[1]:=$FF;
  489.        IPXSendPacket(SendECB);
  490.        IPXGetIntervalMarker(SendMarker);
  491.        end;
  492.  IF Timeout(ListenMarker,currMarker,17) { fake an "hang-up" if no msgs received during 17 secs }
  493.   then begin
  494.        ReadData[1]:=$1B;
  495.        RemoteWindow;
  496.        end;
  497. UNTIL (ReadData[1]=$1b) or (SendData[1]=$1b); { .. until either party has hung up }
  498.  
  499. SendData[1]:=$1b;
  500. IPXSendPacket(SendECB);
  501. IpxCloseSocket(Socket);
  502. Writeln;
  503. Writeln;
  504. writeln('<Hanging Up...........>');
  505. Delay(2000);
  506. Window(1,1,80,25);
  507. LowVideo;
  508. gotoxy(80,25);
  509. end;
  510.  
  511. {--------------- ProcessInputCommand----------------------------------------}
  512.  
  513. Type PusrInfo=^TusrInfo;
  514.      TusrInfo=record
  515.               ObjName :String[47];
  516.               FullName:String[40];
  517.               ConnId,
  518.               ConnNbr :Byte;
  519.               Address :TinterNetworkAddress; { socket field not used }
  520.               next    :PusrInfo;
  521.               end;
  522.  
  523. Var startInfo:PusrInfo;
  524.  
  525. Procedure PushInLL(_objName,_objFullName:String;
  526.                    _connId,_connNbr:Byte;
  527.                    _address:TinternetworkAddress);
  528. Var p,m,l:PusrInfo;
  529. begin
  530. p:=startInfo;
  531. new(l);
  532. With l^
  533.  do begin
  534.     if _objFullName[0]>#40
  535.      then _objFullName[0]:=#40;
  536.     objName:=_objName;
  537.     fullName:=_objFullName;
  538.     connId:=_connId;
  539.     connNbr:=_connNbr;
  540.     address:=_address;
  541.     next:=NIL;
  542.     end;
  543. if p=NIL
  544.  then startInfo:=l
  545.  else begin
  546.       m:=p;
  547.       While (p<>NIL) and (p^.objName<=_obJname)
  548.        do begin m:=p;p:=p^.next; end;
  549.       if p=startInfo
  550.        then begin { insert before first LL entry }
  551.             l^.next:=startInfo;
  552.             startInfo:=l;
  553.             end
  554.        else begin { insert in LL or append to end }
  555.             l^.next:=m^.next;
  556.             m^.next:=l;
  557.             end;
  558.       end;
  559. end;
  560.  
  561. Function GetTargetUser:PusrInfo;
  562. { returns NIL if a target user was not uniquely identified by the user }
  563. Var l            :PusrInfo;
  564.     serverName   :String;
  565.     SelectedUsers:Word;
  566.     t            :Word;
  567.     s            :String;
  568.     ch           :char;
  569.     Laddr        :TinternetworkAddress;
  570.     AddrSame     :boolean;
  571. begin
  572. { are all objNames the same?
  573.    Yes => multple logins (connNbr must have been supplied)
  574.           or login on multiple servers (serverName must h.b. supplied)
  575.    No => the supplied userName is not unique. }
  576. l:=startInfo;
  577. SelectedUsers:=0;
  578. IF l<>NIL
  579.  then Laddr:=l^.address;
  580. AddrSame:=true;
  581. While (l<>NIL)
  582.  do begin
  583.     inc(SelectedUsers);
  584.     AddrSame:=AddrSame and SameAddress(Laddr,l^.address);
  585.     l:=l^.next;
  586.     end;
  587. If AddrSame { are all the users essentially the same ? }
  588.  then SelectedUsers:=1;
  589.  
  590. CASE SelectedUsers of
  591.  0:begin
  592.    GetTargetUser:=NIL;
  593.    end;
  594.  1:begin { OK! unique users identified }
  595.    GetTargetUser:=StartInfo;
  596.    end;
  597.  else begin
  598.       writeln('The target user has multiple connections.');
  599.       writeln('Please give connection number and/or server name of the intended user.');
  600.       writeln;
  601.       writeln('Username             | Server          | Con | Full Name');
  602.       writeln('---------------------+-----------------+-----+----------------------');
  603.  
  604.       t:=3;
  605.       l:=startInfo;
  606.       while l<>NIL
  607.        do begin
  608.           GetFileServerName(l^.connId,servername);
  609.           PstrCopy(s,l^.objName,20);
  610.           write(s,' | ');
  611.           PstrCopy(s,serverName,15);
  612.           write(s,' | ',l^.connNbr:3,' | ');
  613.           PstrCopy(s,l^.fullname,30);
  614.           writeln(s);
  615.           l:=l^.next;
  616.           inc(t);
  617.           if t=20
  618.            then begin
  619.                 writeln('--- more (any key)---');
  620.                 repeat {} until keypressed;
  621.                 ch:=readkey;
  622.                 if ch=#0 then ch:=readkey;
  623.                 t:=0;
  624.                 end;
  625.           end;
  626.       GetTargetUser:=NIL;
  627.       end;
  628.  end; {case}
  629. end;
  630.  
  631. Procedure ProcessInputCommand;
  632. Var SearchStartServer,
  633.     SearchEndServer   :Byte;
  634.     ConnIdCtr,
  635.     ConnNbrCtr        :Byte;
  636.  
  637.     LuserName,
  638.     LserverName       :String;
  639.     LconnId           :Byte;
  640.     LfullName         :String;
  641.     LconnNbr          :Byte;
  642.  
  643.     ServerInfo        :TFileServerInformation;
  644.     objName           :String;
  645.     objType           :Word;
  646.     objId             :Longint;
  647.     ticks             :Word;
  648.     LoginTime         :TnovTime;
  649.     IntNWaddress      :TinternetworkAddress;
  650.  
  651.     TargetUserPtr     :PusrInfo;
  652.  
  653.     p                 :Byte;
  654.     errcode           :Integer;
  655. begin
  656. StartInfo:=NIL;
  657. If (ParamCount>0)
  658.    and ( (pos('?',paramstr(1))>0)
  659.          or (pos('help',paramstr(1))>0)
  660.          or (pos('HELP',paramstr(1))>0)
  661.        )
  662.  then begin
  663.       writeln;
  664.       writeln('** Phone V 1.3., By E.M. Serrat and R. Spronk');
  665.       writeln;
  666.       writeln('** Usage: PHONE');
  667.       writeln;
  668.       writeln('Listen for others calling you.');
  669.       writeln;
  670.       writeln;
  671.       writeln('** Usage: PHONE [servername/]UserName [connection]');
  672.       writeln;
  673.       writeln('Call someone.');
  674.       writeln('-Username may be a ''*'' wildcard.');
  675.       writeln(' All logged in users on all attached servers will be shown.');
  676.       writeln('-Sender and receiver must be attached to a common server in the internetwork.');
  677.       writeln('-The supplied username is compared with the first characters of');
  678.       writeln(' the login name and with the full user name, as set by SYSCON.');
  679.       writeln('-Servername must be supplied if the target user has connections');
  680.       writeln(' with more than one server.');
  681.       writeln('-ConnectionNumber must be supplied if the target user is logged in');
  682.       writeln(' at multiple workstations attached to the same server.');
  683.       writeln;
  684.       writeln('The program will timeout if the program on the other end of the link');
  685.       writeln('is terminated abnormally.');
  686.       halt(1);
  687.       end;
  688. if paramcount=0 { ---- Listen if anyone is calling us ----- }
  689.  then begin
  690.       HandshakeWithSender;
  691.       InitWindows;
  692.       Talk;
  693.       IpxCloseSocket(Socket);
  694.       SetPreferredConnectionId(MyServerId);
  695.       halt(0);
  696.       end;
  697. { ** Paramcount>0, We're calling someone ** }
  698. LconnNbr:=0;
  699. SearchStartServer:=1;
  700. SearchEndServer:=8;
  701. LuserName:=ParamStr(1);
  702. UpString(LuserName);
  703. p:=pos('/',LuserName);
  704. checkError((p=1) and (LuserName[0]=#1),$0020,'');
  705. if p>0
  706.  then begin
  707.       LserverName:=copy(LuserName,1,p-1);
  708.       delete(LuserName,1,p);
  709.       if LuserName=''
  710.        then LuserName:='*';
  711.       if pos('*',LserverName)=0
  712.        then begin
  713.             GetConnectionId(LserverName,LconnId);
  714.             checkError(nwConn.result>0,$0022,LserverName);
  715.             SearchStartServer:=LconnId;
  716.             SearchEndServer:=LconnId;
  717.             end;
  718.       end;
  719. if paramcount>1
  720.  then begin
  721.       Val(ParamStr(2),LconnNbr,errcode);
  722.       checkError(errcode<>0,$0023,Paramstr(2));
  723.       end;
  724.  
  725. writeln('Scanning logged in users..');
  726. ConnIdCtr:=SearchStartServer;
  727. While ConnIdCtr<=SearchEndServer
  728.  do begin
  729.     If IsConnectionIdInUse(ConnIdCtr)
  730.      then begin
  731.           SetPreferredConnectionId(ConnIdCtr);
  732.           IF NOT GetFileServerInformation(ServerInfo)
  733.            then ServerInfo.connectionsMax:=250; { patch value if call failed }
  734.           for ConnNbrCtr:=1 to ServerInfo.ConnectionsMax
  735.            do begin
  736.               IF GetConnectionInformation(ConnNbrCtr,ObjName,objType,objId,LoginTime)
  737.                  and (objType=OT_USER)
  738.                then begin
  739.                     GetInterNetAddress(ConnNbrCtr,IntNWaddress);
  740.                     GetRealUserName(ObjName,LfullName);
  741.                     UpString(LfullName);
  742.                     IF (pos('NOT-LOGGED-',objName)=0)        { skip not logged in connections }
  743.                       and ((LconnNbr=0) or (LconnNbr=ConnNbrCtr))     { if user supplied connNbr, check it }
  744.                       and (NOT SameAddress(MyAddress,IntNWAddress)) { no mail to yourself }
  745.                       and ( (LuserName[1]='*')               { wildcard overrules nameselection }
  746.                             or (pos(LuserName,ObjName)=1)    { username matched with firts few characters in objName? }
  747.                             or (pos(LuserName,LfullName)>0)  { usermane matches part of objects' Full_Name ? }
  748.                           )
  749.                      then PushInLL(objName,LfullName,ConnIdCtr,ConnNbrCtr,
  750.                                    IntNWaddress);
  751.                     end;
  752.               end;
  753.           end;
  754.     inc(ConnIdCtr);
  755.     end;
  756. TargetUserPtr:=GetTargetUser;
  757. checkError((LuserName[1]<>'*') and (TargetUserPtr=NIL),$0025,''); { No user selected }
  758. checkError(TargetUserPtr=NIL,$0026,'');
  759. RconnNbr:=TargetUserPtr^.connNbr;
  760. Raddress:=TargetUserPtr^.address;
  761. Raddress.Socket:=Socket;
  762. Rname:=TargetUserPtr^.objName;
  763. RserverId:=TargetUserPtr^.connId;
  764. GetFileServerName(RserverId,RserverName);
  765. release(HeapCheckPtr);
  766.  
  767. SetPreferredConnectionId(RserverId);
  768. GetRealUserName(Rname,RfullName);
  769. writeln;
  770. writeln(RserverName,'/',Rname,' Connection_Number= ',RconnNbr);
  771. writeln('(Full name =',RfullName,')');
  772. writeln;
  773. write('Is the above user the intended chat partner ? (Y/N)');
  774. checkError(NOT Confirm,$0027,''); { user abort }
  775. writeln;
  776.  
  777. IPXGetLocalTarget(Raddress,LocalTarget,ticks);
  778. IPXSetupSendECB(NIL, Socket, Raddress, Addr(SendData), SizeOf(SendData),
  779.                 SendIPXheader,SendECB);
  780. HandShakeWithReceiver;
  781. InitWindows;
  782. Talk;
  783. IpxCloseSocket(Socket);
  784. SetPreferredConnectionId(MyServerId);
  785. halt(0);
  786. end;
  787.  
  788. Procedure WhoAmI; {---------------------------------------------------------}
  789. Var ObjType  :Word;
  790.     ObjId    :LongInt;
  791.     LogonTime:TnovTime;
  792. begin
  793. GetConnectionNumber(MyConnNbr);
  794. checkError(nwConn.result>0,$0010,'');
  795. GetInternetAddress(MyConnNbr,MyAddress);
  796. checkError(nwConn.result>0,$0011,'');
  797. MyAddress.Socket:=Socket;
  798. GetConnectionInformation(MyConnNbr,MyName,ObjType,ObjId,LogonTime);
  799. checkError(nwConn.result>0,$0012,'');
  800. GetEffectiveConnectionID(MyServerId);
  801. GetFileServerName(MyServerId,MyServerName);
  802. end;
  803.  
  804. {-----------------------------------------------------------------------------}
  805. Var LocSocket:Word;
  806.  
  807. begin
  808. Writeln('*** PHONE V1.3 ***');
  809. Mark(HeapCheckPtr);
  810. LocSocket:=Socket;
  811. readflg:=false;
  812. Checkerror(NOT IpxPresent,$0001,'');
  813. IpxOpenSocket(LocSocket,FALSE);
  814. Checkerror(nwIPX.result>0,$0002,'');
  815. WhoAmI;
  816. IPXSetupListenECB(Addr(EsrHandler),socket,Addr(ReadData),SizeOf(ReadData),
  817.                   ListenIPXheader,ListenECB);
  818. ProcessInputCommand; {doesn't return}
  819. end.